#include "drv_UART_Console.h"

#ifdef RT_USING_CONSOLE

// 存放shell串口接收字节的邮箱
static rt_mailbox_t consoleRCV = RT_NULL;


/********************* shell使用的串口函数*************************/
void UartConsoleInit(void)
{
    REG_UART1_APB_IER = 0x00; // 禁止所有中断 可靠性设计
    REG_UART1_APB_MCR = 0;    // 禁止红外功能 禁止流控制和回环

    REG_UART1_APB_LCR = 0x80; // 设置波特率分频系数地址可写
    // 波特率设置 115200
    REG_UART1_APB_DLH = UART_APB_BAUD115200_DLH;
    REG_UART1_APB_DLL = UART_APB_BAUD115200_DLL;

    // 无校验 8bit 1个停止位
    REG_UART1_APB_LCR = 0x03;

    REG_UART1_APB_FCR = 0x07; // 清FIFO 允许FIFO

    // 中断初始化
    rt_hw_interrupt_install(UART1_APB_IRQ_NUMBER, UartConsoleISR, RT_NULL, "Console");
    rt_hw_interrupt_umask(UART1_APB_IRQ_NUMBER);

    REG_UART1_APB_IER = 0x01; // 打开接收中断
    // REG_UART1_APB_IER = 0x00; //禁止所有中断

    return;
}

void UartConsoleSendOneByte(rt_uint8_t dat)
{
    rt_uint16_t tmp = 50000;

    while (--tmp) // 设置倒计时100us@500MHz 防止锁死
    {
        if ((REG_UART1_APB_LSR & 0x20) > 0) // 发送寄存器空则退出循环开始发送
        {
            break;
        }
        else{}
    }

    REG_UART1_APB_THR = dat;

    return;
}

char UartConsoleReadOneByte(int *dat)
{
    rt_uint32_t tmp = 0;
    tmp = REG_UART1_APB_LSR;

    if (1 == (tmp & 0x01)) // 如果接收标识为1 读入数据
    {
        *dat = (int)REG_UART1_APB_RBR;
        return 1;
    }
    else
    {
        rt_thread_mdelay(10);
        return -1;
    }
}

int UartConsoleMailBoxInit(void)
{
    consoleRCV = rt_mb_create("consoleRCV", 4, RT_IPC_FLAG_FIFO);

    if (consoleRCV == RT_NULL)
    {
        rt_kprintf("RT-Thread create mailbox failed\n");
    }
    else{}

    return 0;
}
INIT_APP_EXPORT(UartConsoleMailBoxInit); // 自动初始化 在最后调用

// 邮箱发送函数 用于将串口收到的数据通过邮箱发送
void UartConsoleMailBoxSend(rt_uint32_t value)
{
    rt_err_t er = RT_NULL;

    er = rt_mb_send(consoleRCV, value);
    if (-RT_EFULL == er)
    {
        rt_kprintf("MailBox consoleRCV is full,send error\n");
    }
    else{}

    return;
}

// 邮箱接收函数 用于接收串口数据 传递给finsh
char UartConsoleMailBoxRecv(void)
{
    char res = -1;
    rt_ubase_t dat = 0; // 接收邮箱数据

    if (RT_EOK == rt_mb_recv(consoleRCV, &dat, RT_WAITING_FOREVER))
    {
        res = (char)(dat & 0xff);
    }
    else
    {
        rt_kprintf("MailBox consoleRCV receive error\n");
    }

    return res;
}

// 串口中断服务程序 接收数据并发送邮件
void UartConsoleISR(int vector, void *param)
{
    rt_uint32_t tmp = 0;
    rt_base_t level = 0; // 保存发送异常时候关中断 避免printf不可重入
    rt_interrupt_enter();

    tmp = REG_UART1_APB_IIR & 0x0f;
    if (0x04 == tmp) // 收到数据
    {
        UartConsoleMailBoxSend(REG_UART1_APB_RBR);
    }
    else
    {
        level = rt_hw_interrupt_disable();
        rt_kprintf("Console Uart Interrupt ID error\n");
        rt_hw_interrupt_enable(level);
    }

    rt_interrupt_leave();

    rt_hw_interrupt_ack(UART1_APB_IRQ_NUMBER);
}

#endif